#!/usr/bin/env python
#coding=utf-8
import sys
import os
import logging
import types
import importlib
from tornado import web
from tornado.ioloop import IOLoop
from tornado.httpserver import HTTPServer
from tornado.options import parse_command_line
from beaker.cache import CacheManager
from beaker.util import parse_cache_config_options
from mako.lookup import TemplateLookup
from tornado.options import options, define
from handlers.base import BaseHandler
from tornado.log import enable_pretty_logging
from handlers.base import PageNotFoundHandler
from settings import config

from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy import create_engine
import db_models

enable_pretty_logging()

define('debug', type=bool, default=True)
define('port', type=int, default=9797)


class Application(web.Application):
    app_urls = [(r'/favicon.ico', web.StaticFileHandler, {'path': "/static/favicon.ico"}),
                ('.*', PageNotFoundHandler), ]

    def __init__(self):
        super(Application, self).__init__(self.app_urls,**config)

        db_models.engine = create_engine(config['dburl'], echo=False, pool_size=5, max_overflow=5)

        self.db = scoped_session(sessionmaker(bind=db_models.engine, autocommit=False, autoflush=False))


        self.cache = CacheManager(**parse_cache_config_options({
            'cache.type': 'file',
            'cache.data_dir': './tmp/cache/data',
            'cache.lock_dir': './tmp/cache/lock'
        }))

        self.tp_lookup = TemplateLookup(directories=['./templates'],
                                        default_filters=['decode.utf8'],
                                        input_encoding='utf-8',
                                        output_encoding='utf-8',
                                        encoding_errors='replace',
                                        module_directory="./tmp")

        self.logging = logging.getLogger('app:logging')


    def load_module(self, modules, **options):
        for module in modules:
            print u'loadding module %s' % module.__name__

            assert type(module) is types.ModuleType
            host_pattern = options.get('host_pattern', '.*$')

            # 处理加载 RequestHandler 和路由规则
            cls_valid = lambda cls: type(cls) is types.TypeType and issubclass(cls, BaseHandler)  # 是否有效
            url_valid = lambda cls: hasattr(cls, 'url_pattern') and cls.url_pattern  # 是否拥有 url 规则
            mod_attrs = (getattr(module, i) for i in dir(module) if not i.startswith('_'))
            valid_handlers = ((i.url_pattern, i) for i in mod_attrs if cls_valid(i) and url_valid(i))


            # 处理完毕载入
            self.add_handlers(host_pattern, valid_handlers)

    def _get_host_handlers(self, request):
        host = request.host.lower().split(':')[0]
        handlers = (i for p, h in self.handlers for i in h if p.match(host))
        if not handlers and "X-Real-Ip" not in request.headers:
            handlers = [i for p, h in self.handlers for i in h if p.match(self.default_host)]
        return handlers


def main():
    os.environ['PYTHON_EGG_CACHE'] = '/tmp/.python-eggs'
    path = os.path.dirname(os.path.abspath(__file__))
    if path not in sys.path:
        sys.path.insert(0, path)

    parse_command_line()
    if options.debug:
        logging.info('Starting server at port %s in debug mode' % options.port)
    else:
        logging.info('Starting server at port %s' % options.port)

    hds = set(os.path.splitext(it)[0] for it in os.listdir('./handlers'))
    hds = [it for it in hds if it not in ('__init__', 'base')]
    hdmodules = []
    for hd in hds:
        try:
            hdmodules.append(importlib.import_module('handlers.%s' % hd))
        except:
            continue
    app = Application()
    app.load_module(hdmodules)

    server = HTTPServer(app, xheaders=True)
    server.listen(int(options.port), '0.0.0.0')
    IOLoop.instance().start()


if __name__ == '__main__':
    try:
        main()
    except (EOFError, KeyboardInterrupt):
        print("\nExiting application")
